package com.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alipay.sofa.runtime.api.annotation.SofaService;
import com.alipay.sofa.runtime.api.annotation.SofaServiceBinding;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.context.ManagerContext;
import com.domain.dto.PageDTO;
import com.domain.dto.ProductsDTO;
import com.domain.dto.ProxyDto;
import com.domain.dto.StateDTO;
import com.domain.po.*;
import com.domain.query.ProductQuery;
import com.domain.query.RecordListQuery;
import com.domain.vo.ProductDetailsVO;
import com.domain.vo.ProductVO;
import com.domain.vo.RecordVO;
import com.enums.ProductStart;
import com.exception.DbException;
import com.mapper.*;
import com.service.ProductDetalisService;
import com.service.ProductPriceService;
import com.service.ProductService;
import com.service.ProxyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@SofaService(interfaceType = ProductService.class, bindings = {@SofaServiceBinding(bindingType = "bolt")})
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    @Autowired
    SupplierMapper supplierMapper;
    @Autowired
    ProductMapper productMapper;
    @Autowired
    ProxyService proxyService;
    @Autowired
    ProductDetalisService productDetalisService;
    @Autowired
    ProductDetalisMapper productDetalisMapper;
    @Autowired
    ProductPriceMapper productPriceMapper;
    @Autowired
    ProductPriceService productPriceService;
    @Autowired
    ProductCategoryMapper productCategoryMapper;
    @Autowired
    OperateRecordMapper operateRecordMapper;

    /**
     * 编辑商品信息
     *
     * @param productsDTO 商品信息
     */
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "productCache", key = "#productsDTO.productId")
    public void updateProduct(ProductsDTO productsDTO) {
        Product product1 = productMapper.selectById(productsDTO.getProductId());
        if (product1 == null) {
            throw new DbException("没有找到该商品");
        }
        try {
            /**
             * 更新商品基本信息表
             */
//将productDTO中有关商品表的内容传到实例product中

            Product product = BeanUtil.copyProperties(productsDTO, Product.class);
            product.setProductState(ProductStart.CHECK.getValue());
            productMapper.updateById(product);
/**
 * 更新商品详情表
 */
            //通过商品id从商品表中获得商品详细的id
            Product prouduct1 = this.getById(productsDTO.getProductId());
            //通过商品详情表查找供应商的id传到实例productDetalis中
            ProductDetalis productDetalis1 = productDetalisMapper.selectById(prouduct1.getProductDetailsId());
            //获取不发货城市和投放城市
            List<String> cityWhitelist = productsDTO.getCityWhitelist();
            List<String> cityBlacklist = productsDTO.getCityBlacklist();
            //将cityWhitelis、cityBlacklist转为字符串使用逗号隔开
            String cityWhitelistString = StringUtils.join(cityWhitelist, ",");
            String cityBlacklistString = StringUtils.join(cityBlacklist, ",");


            ProductDetalis productDetalis = BeanUtil.copyProperties(productsDTO, ProductDetalis.class);
            productDetalis.setProductDetailsId(prouduct1.getProductDetailsId());
            productDetalis.setCityBlacklist(cityBlacklistString); //不发货城市
            productDetalis.setCityWhitelist(cityWhitelistString);//投放城市
            productDetalis.setUpdateTime(LocalDateTime.now());//修改时间
            productDetalis.setProductSupplierId(productDetalis1.getProductSupplierId());//供应商id
            productDetalisMapper.updateById(productDetalis);
/**
 * 更新商品兑换表
 */

            QueryWrapper<ProductPrice> wrapper0 = new QueryWrapper<ProductPrice>()
                    .eq("product_id", productsDTO.getProductId());
            productPriceService.remove(wrapper0);
            List<ProductPrice> productPriceList = productsDTO.getProductExchangeType();
            if (productPriceList != null && productPriceList.size() > 0) {
                productPriceList.forEach(productPrice -> {
                    productPrice.setProductId(productsDTO.getProductId());
                });
                productPriceService.saveBatch(productPriceList);
            }

/**
 * 更新供应商表
 */
            Supplier supplier = Supplier.builder()
                    .productSupplierId(productDetalis1.getProductSupplierId())
                    .supplierName(productsDTO.getSupplierName())
                    .supplierPhone(productsDTO.getSupplierPhone())
                    .supplierSafeguard(productsDTO.getSupplierSafeguard())
                    .build();

            supplierMapper.updateById(supplier);


            /**
             *更新代理人表
             */
            QueryWrapper<Proxy> wrapper1 = new QueryWrapper<Proxy>()
                    .eq("product_id", productsDTO.getProductId());
            proxyService.remove(wrapper1);
            List<Proxy> proxies = productsDTO.getProxys();
            if (proxies != null && proxies.size() > 0) {
                proxies.forEach(proxy -> {
                    proxy.setProductId(productsDTO.getProductId());
                });
                proxyService.saveBatch(proxies);
            }
        } catch (Exception e) {
            throw new DbException("更新失败");
        }
        //如果修改商品状态，就往商品状态操作记录表添加本次信息
        if (productsDTO.getProductState() != null) {
            insertOperationRecord(productsDTO.getProductId(), productsDTO.getProductState(), productsDTO.getManagerId());
        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createProduct(ProductsDTO productsDTO) {
        log.info("新增商品信息开始");
        try {

            Long managerId = productsDTO.getManagerId();

            //1. 保存供应商信息
            Supplier supplier = BeanUtil.copyProperties(productsDTO, Supplier.class);
            supplierMapper.insert(supplier);
            log.info("新增供应商信息成功");

            //2. 保存商品详情信息
            ProductDetalis productDetalis = BeanUtil.copyProperties(productsDTO, ProductDetalis.class);

            //2.1 获取投放城市 和不发货城市
            List<String> cityWhitelist = productsDTO.getCityWhitelist();
            String cityWhitelistString;
            if (cityWhitelist.isEmpty()) {
                throw new DbException("未设置投放城市");

            } else {
                //将cityWhitelist转为字符串使用逗号隔开
                cityWhitelistString = StringUtils.join(cityWhitelist, ",");
            }


            List<String> cityBlacklist = productsDTO.getCityBlacklist();
            //将cityBlacklist转为字符串使用逗号隔开
            String cityBlacklistString = StringUtils.join(cityBlacklist, ",");
            productDetalis.setCityWhitelist(cityWhitelistString);
            productDetalis.setCityBlacklist(cityBlacklistString);
            productDetalis.setProductSupplierId(supplier.getProductSupplierId());
            productDetalis.setCreateTime(LocalDateTime.now());
            productDetalis.setUpdateTime(LocalDateTime.now());

            productDetalis.setCreateUserId(managerId);

            //2.2 向数据库中存储商品详情信息
            productDetalisMapper.insert(productDetalis);
            log.info("新增详情信息成功");

            //3. 保存商品基本信息
            Product product = BeanUtil.copyProperties(productsDTO, Product.class);
            product.setProductDetailsId(productDetalis.getProductDetailsId());
            product.setRemainingStock(productsDTO.getInStock());

            productMapper.insert(product);

            //4. 保存代理人信息
            List<Proxy> proxys = productsDTO.getProxys();

            if (proxys != null) {
                //使用foreach遍历代理人列表将代理人实体中设置上商品Id
                proxys.forEach(proxy -> {
                    proxy.setProductId(product.getProductId());
                });
                proxyService.saveBatch(proxys);
                log.info("新增代理人信息成功");
            }

            //5. 保存商品兑换类型信息
            List<ProductPrice> productExchangeType = productsDTO.getProductExchangeType();
            //使用foreach遍历商品兑换类型列表将商品兑换类型实体中设置上商品Id
            if (productExchangeType != null) {
                productExchangeType.forEach(productPrice -> {
                    productPrice.setProductId(product.getProductId());
                });
                productPriceService.saveBatch(productExchangeType);
                log.info("新增商品兑换信息成功");
            }

            //新增操作记录
            insertOperationRecord(product.getProductId(), productsDTO.getProductState(), managerId);
            log.info("新增商品完成,商品Id{}", product.getProductId());

        } catch (Exception e) {
            log.info("新增商品错误{}", e.getMessage());
            throw new DbException("新增商品错误");
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Cacheable(cacheNames = "productCache", key = "#productId")
    public ProductDetailsVO queryByProductId(Long productId) {

        log.info("查询商品详情信息开始");
        try {
            //1. 根据商品id查询出商品基本信息
            Product product = productMapper.selectById(productId);
            log.info("查询商品基本信息成功:商品id{}", productId);

            if (product == null) {
                throw new DbException("商品id不存在");
            }

            //2. 根据商品基本表中的商品详情id查询出商品详情信息
            ProductDetalis productDetalis = productDetalisMapper.selectById(product.getProductDetailsId());
            log.info("查询商品详情信息成功:商品id{}", productId);

            //3. 根据商品详情信息中的分类id查询查分类名称
            ProductCategory productCategory = productCategoryMapper.selectById(productDetalis.getProductCategoryId());
            log.info("查询商品分类信息成功:商品id{}", productId);

            //4. 根据商品详情信息中的供应商id 查询出供应商信息
            Supplier supplier = supplierMapper.selectById(productDetalis.getProductSupplierId());
            log.info("查询商品供应商信息成功:商品id{},供应商id{}", productId, productDetalis.getProductSupplierId());

            //5. 根据商品id 查询代理人信息
            List<Proxy> proxyList = proxyService.lambdaQuery()
                    .eq(Proxy::getProductId, productId)
                    .list();
            log.info("查询商品代理人信息成功:商品id{}", productId);

            //6. 根据商品id 查询商品价格类型信息
            List<ProductPrice> productPriceList = productPriceService.lambdaQuery()
                    .eq(ProductPrice::getProductId, productId)
                    .list();
            log.info("查询商品价格类型信息成功:商品id{}", productId);

            //7. 封装Vo
            ProductDetailsVO productDetailsVO = new ProductDetailsVO();

            //7.1 将商品基本信息信息copy到vo中
            BeanUtil.copyProperties(product, productDetailsVO);
            //7.2 将商品详情信息copy到vo中
            BeanUtil.copyProperties(productDetalis, productDetailsVO);
            //7.3 将供应商信息copy到vo中
            BeanUtil.copyProperties(supplier, productDetailsVO);
            //设置vo的其他信息
            productDetailsVO.setProductExchangeType(productPriceList);
            productDetailsVO.setProxys(proxyList);
            //根据逗号分割出每一个城市信息

            String cityWhitelist1 = productDetalis.getCityWhitelist();
            String cityBlacklist1 = productDetalis.getCityBlacklist();
            if (cityWhitelist1 != null) {
                String[] split = cityWhitelist1.split(",");
                List<String> cityWhitelist = Arrays.asList(split);
                productDetailsVO.setCityWhitelist(cityWhitelist);
            }
            if (cityBlacklist1 != null) {
                String[] split = cityBlacklist1.split(",");
                List<String> cityBlacklist = Arrays.asList(split);
                productDetailsVO.setCityBlacklist(cityBlacklist);
            }

            productDetailsVO.setProductCategoryName(productCategory.getProductCategoryName());
            productDetailsVO.setProductTypeName(productCategory.getProductType());
            log.info("VO封装成功,redis缓存中没有，通过mysql查找");

            return productDetailsVO;

        } catch (Exception e) {
            throw new DbException("根据Id查询商品有误");
        }
    }

    @Override
    public PageDTO<ProductVO> productListPage(ProductQuery productQuery) {
        try {

            log.info("商品基本信息分页查询开始");
            Long managerId = productQuery.getManagerId();
            Integer productState = productQuery.getProductState();
            Long productId = productQuery.getProductId();
            String productName = productQuery.getProductName();
            LocalDate timeOn = productQuery.getTimeOn();
            LocalDate timeOff = productQuery.getTimeOff();
            String managerName = productQuery.getManagerName();

            //1. 查询当前登录者和商品的关系（0不是代理 1是代理，2创建）
            //1.1 根据登录者id在代理人表中查询该登录者代理的商品id
            List<Proxy> proxyList = proxyService.lambdaQuery()
                    .eq(managerId != null, Proxy::getManagerId, managerId)
                    .select(Proxy::getProductId)
                    .list();

            //1.2 在商品基本信息表中根据登录者id查询出该登录者创建的商品id
            List<Long> productIds = productMapper.selectByUserId(managerId);

            //1.3 创建hashMap 以商品id为key 商品关系为值（3不是代理 1是代理，2创建）
            HashMap<Long, Integer> productRelationHashMap = new HashMap<>(proxyList.size() + productIds.size());
            proxyList.forEach(proxy -> {
                productRelationHashMap.put(proxy.getProductId(), 1);
            });
            productIds.forEach(item -> {
                productRelationHashMap.put(item, 2);
            });

            //2. 构建分页条件
            Page<Product> page = productQuery.toMpPage("time_On", true);

            //3. 分页查询
            Page<Product> p = lambdaQuery()
                    .eq(productState != null, Product::getProductState, productState)
                    .eq(productId != null, Product::getProductId, productId)
                    .like(StringUtils.isNoneEmpty(managerName), Product::getManagerName, managerName)
                    .like(StringUtils.isNoneEmpty(productName), Product::getProductName, productName)
                    .ge(timeOn != null, Product::getTimeOn, timeOn)
                    .le(timeOff != null, Product::getTimeOff, timeOff)
                    .page(page);
            log.info("商品基本信息分页查询成功");

            //4. 封装Vo
            PageDTO<ProductVO> productVOPageDTO = PageDTO.of(p, product -> {
                //将product拷贝到productVo中
                ProductVO productVO = BeanUtil.copyProperties(product, ProductVO.class);
                //保证精度不丢失 将id转为字符串返回给前端
                productVO.setStrProductId(String.valueOf(product.getProductId()));
                //根据商品关系hashMap 修改代理状态
                Integer isProxy = productRelationHashMap.get(productVO.getProductId());
                if (isProxy == null) {
                    productVO.setIsProxy(3);
                } else {
                    productVO.setIsProxy(isProxy);
                }
                return productVO;
            });
            log.info("vo封装成功");

            log.info("商品基本信息分页查询完成{}", productVOPageDTO.toString());
            return productVOPageDTO;
        } catch (Exception e) {
            throw new DbException("分页查询有误");
        }
    }

    /**
     * 修改商品状态
     *
     * @param stateDTO
     */
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "productCache", key = "#stateDTO.productId")
    @Override
    public void updateState(StateDTO stateDTO) {
        // 检查stateDTO和productId是否有效
        if (stateDTO.getProductId() == null || stateDTO.getProductState() == null) {
            throw new DbException("传入参数不合法");
        }
        Product product = productMapper.selectById(stateDTO.getProductId());
        if (product == null) {
            throw new DbException("没有找到该商品");
        }
        ProductDetalis productDetalis = productDetalisMapper.selectById(product.getProductDetailsId());
//        //如果驳回理由和成功理由都存在，则抛出异常
//        if(stateDTO.getProductRejectMsg() != null || stateDTO.getProductAgreeMsg() != null){
//            throw new DbException("驳回理由和成功理由不能同时存在");
//        }
        //如果驳回理由存在，将驳回理由插入详情表里
        if (stateDTO.getProductRejectMsg() != null) {
            productDetalis.setProductRejectMsg(stateDTO.getProductRejectMsg());
            //更新数据库
            productDetalisMapper.updateById(productDetalis);
        }
        //如果审核成功理由存在，将成功理由插入详情表里
        if (stateDTO.getProductAgreeMsg() != null) {
            productDetalis.setProductAgreeMsg(stateDTO.getProductAgreeMsg());
            //更新数据库
            productDetalisMapper.updateById(productDetalis);
        }

        product.setProductState(stateDTO.getProductState());
        // 保存更新后的商品回数据库
        int result = productMapper.updateById(product);

        // 检查更新是否成功
        if (result <= 0) {
            throw new RuntimeException("更新失败");
        }
        //新增操作记录
        insertOperationRecord(stateDTO.getProductId(), stateDTO.getProductState(), stateDTO.getOperationId());

    }

    /**
     * 查看商品操作记录
     *
     * @param recordListQuery
     * @return
     */
    @Override
    public PageDTO<RecordVO> recordListQuery(RecordListQuery recordListQuery) {
        //1.构建查询条件
        Page<OperateRecord> page = recordListQuery.toMpPage("operate_time", true);
        //2.分页查询商品操作记录
        QueryWrapper<OperateRecord> queryWrapper = new QueryWrapper<>();
        if (recordListQuery.getProductId() != null) {
            queryWrapper.eq("product_id", recordListQuery.getProductId());
        }
        Page<OperateRecord> operateRecordPage = operateRecordMapper.selectPage(page, queryWrapper);

        //3.封装VO
        PageDTO<RecordVO> recordVOPageDTO = PageDTO.of(operateRecordPage, operateRecord -> {
            RecordVO recordVO = new RecordVO(); // 创建 RecordVO 对象
            BeanUtil.copyProperties(operateRecord, recordVO); // 使用 BeanUtil 复制属性
            recordVO.setRecordStatus(operateRecord.getProductState());
            recordVO.setProductId(String.valueOf(operateRecord.getProductId()));
            return recordVO; // 返回转换后的 RecordVO 对象
        });
        return recordVOPageDTO;
    }

    /**
     * 修改代理人信息
     * @param proxyDtoList 代理人数据
     */
    public void updateProxy(List<ProxyDto> proxyDtoList) {

        QueryWrapper<Proxy> wrapper1 = new QueryWrapper<Proxy>()
                .eq("product_id", proxyDtoList.get(0).getProductId());
        proxyService.remove(wrapper1);

        List<Proxy> proxyList = proxyDtoList.stream().map(proxyDto -> {
            return BeanUtil.copyProperties(proxyDto, Proxy.class);
        }).collect(Collectors.toList());

        if (proxyDtoList != null && proxyDtoList.size() > 0) {
            ProxyDto proxyDto = proxyDtoList.get(0);
            proxyDtoList.forEach(proxy -> {
                proxy.setProductId(proxyDto.getProductId());
            });
            proxyService.saveBatch(proxyList);
        }

    }


    /**
     * 新建操作记录Id
     *
     * @param productId     商品Id
     * @param recordStatus  商品状态
     * @param operateUserId 操作人Id
     */
    public void insertOperationRecord(Long productId, Integer recordStatus, Long operateUserId) {
        log.info("新增操作记录:商品id:{},商品状态:{},操作人id:{}", productId, recordStatus, operateUserId);

        LocalDateTime operateTime = LocalDateTime.now();
        OperateRecord operateRecord = new OperateRecord();
        operateRecord.setProductId(productId);
        operateRecord.setProductState(recordStatus);
        operateRecord.setOperateTime(operateTime);
        operateRecord.setOperateUserId(operateUserId);
        operateRecordMapper.insert(operateRecord);
        log.info("新增操作记录成功");

    }

}


